const pathUtil = require('path');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const root = process.cwd();

const StylusLoader = {
	test: /\.styl$/,
	use : [
		'style-loader',
		MiniCssExtractPlugin.loader,
		'css-loader',
		'postcss-loader',
		'stylus-loader',
	],
};

const SassBaseLoader = {
	test: /\.s[ac]ss$/i,
	use : [
		// Creates `style` nodes from JS strings
		'style-loader',
		MiniCssExtractPlugin.loader,
		// Translates CSS into CommonJS
		'css-loader',
		'postcss-loader',
		// Compiles Sass to CSS
		{
			loader : 'sass-loader',
			options: {},
		},
	],
};

const phases = {
	phase2(config) {
		config.module.rules.push(StylusLoader);
		config.module.rules.push(SassBaseLoader);
	},
	'mobx-demo': (config) => {
		config.module.rules.push(StylusLoader);
		config.entry = ['react-hot-loader/patch', config.entry[0]];
	}
};

const loaders = {
	babel : {
		test   : /\.m?jsx?$/,
		exclude: /(node_modules|bower_components)/,
		use    : {
			loader : 'babel-loader?cacheDirectory=true',
			options: {
				presets: ['@babel/preset-env', '@babel/preset-react'],
				plugins: [
					"react-hot-loader/babel",
					// 去掉 legacy true, loose true
					// @K.
					// @see https://babeljs.io/docs/en/babel-plugin-proposal-decorators
					['@babel/plugin-proposal-decorators', {'legacy': true}],
					['@babel/plugin-proposal-class-properties', {'loose': true}],
					// @see https://babeljs.io/docs/en/babel-plugin-proposal-private-methods
					// es8 私有属性支持
					// ['@babel/plugin-proposal-private-methods' /*{'loose': true}*/],
					// // @see https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
					// //
					// '@babel/plugin-proposal-optional-chaining',
					// // @see https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator
					// '@babel/plugin-proposal-nullish-coalescing-operator',
					// '@babel/plugin-transform-modules-commonjs',
					// '@babel/plugin-transform-block-scoping',
					// '@babel/plugin-transform-computed-properties',
					// '@babel/plugin-proposal-object-rest-spread',
					// '@babel/plugin-transform-async-to-generator',
					// '@babel/plugin-transform-regenerator',
				],
			},
		},
	},
	images: {
		test: /\.(gif|png|jpg|jpeg)$/,
		use :
			{
				loader : 'file-loader',
				options: {
					name      : '[hash].[ext]',
					outputPath: 'imgs/',
				},
			},
	},
	fonts : {
		test: /\.(woff|woff2|eot|ttf)(\?[\s\S]+)?$/,
		use :
			{
				loader : 'file-loader',
				options: {
					name      : '[hash].[ext]',
					outputPath: 'fonts/',
				},
			},
	},
	css   : {
		test: /\.css$/,
		use : [ // css-loader > MiniCssExtractPlugin.loader > style-loader
			'style-loader',
			MiniCssExtractPlugin.loader,
			'css-loader',
		],
	},
};

module.exports = ({dir}) => {
	const config = {
		entry       : [
			pathUtil.resolve(root, `src/${dir}/app.js`),
		],
		output      : {
			path      : pathUtil.resolve(root, 'dist'),
			publicPath: `/`,
			filename  : 'app.js',
			// libraryTarget: 'umd', // 都以 umd 方式输出
		},
		devServer   : {
			headers         : {'Access-Control-Allow-Origin': '*'},
			disableHostCheck: true,
			port            : 9394,
			contentBase     : 'public',
			allowedHosts    : ['127.0.0.1', 'localhost'],
			host            : '0.0.0.0',
			hot             : true, // 热替换
			compress        : false, // 压缩
		},
		module      : {
			rules: [
				loaders.babel,
				loaders.images,
				loaders.fonts,
				loaders.css,
			],
		},
		plugins     : [
			new MiniCssExtractPlugin({
				filename: `app.css`, // 将 CSS 分离到 app.css 文件上
			}),
		],
		optimization: {},
	};
	
	if (typeof phases[dir] === 'function') {
		phases[dir](config);
	}
	
	return config;
};
